home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Resources / General / ProNET / src / device / pronet.device.s
Text File  |  1999-05-28  |  30KB  |  1,305 lines

  1. *
  2. * pronet.device
  3. *
  4.  
  5. VERSION        equ    38
  6. REVISION    equ    1
  7.  
  8. ******* pronet.device/--Overview-- ******************************************
  9. *
  10. * IMPORTANT: Everything in here is subject to change. This is a "private"
  11. * device, but I've documented it nevertheless. Don't expect your programs
  12. * to run with future versions of the device!
  13. *
  14. * >> GENERAL INFORMATION <<
  15. *
  16. * The device is able to handle several Units, which are defined in the
  17. * `devs:pronet/.config' file. Each Unit corresponds to a certain driver
  18. * and interface. The Units are subdivided into Ports, which are channels
  19. * between two sides of one Unit. This way two application systems may work
  20. * through the same connection without interfering each other.
  21. *
  22. * pronet.device is *not* a SANA-II compliant networking device, and it is not
  23. * compatible to any other exec device, because it's got some very strange
  24. * behaviour regarding incoming data.  Sometimes it is useful, sometimes it is
  25. * not, but I will not change this anyway:  CMD_READ is not supported, instead
  26. * of that, when opening the device, you specify a MsgPort to which all
  27. * incoming data will be sent automatically, if you want it or not!
  28. *
  29. * pronet.device v37 is incompatible to ProNET applications written
  30. * earlier, see below. I'm sorry for that, but I've not heard from people
  31. * using this device anyway ;-)
  32. *
  33. * >> ERROR CODES <<
  34. *
  35. * pronet.device v37 can return one of the following error codes after
  36. * OpenDevice():
  37. *
  38. * PNDERR_PORTEXISTS
  39. *    You've tried to open up a Port which is already in use.
  40. *
  41. * PNDERR_DRIVERTROUBLE
  42. *    The driver of the Unit you requested can not be started.
  43. *    You can request a more detailed error message by setting the
  44. *    according bit in OpenDevice()/Flags. pnr_Data must then point to
  45. *    a buffer provided by you. The string will not exceed 63 characters
  46. *    plus the terminating zero. If no error occurs, the buffer will
  47. *    not be changed!
  48. *
  49. * PNDERR_UNIT_NOT_DEFINED
  50. *    The Unit you requested is missing a definition in the config file.
  51. *
  52. * >> CHANGES SINCE V3 <<
  53. *
  54. * v37: Write doesn't support two chunks anymore, Write can fail
  55. *    with PNDERR_DESTINATION_GONE now, no more #?ConfigString() in order
  56. *    to keep the configuration file tidy. Structure of received data
  57. *    has changed. PNB_ERRORSTRING.
  58. *
  59. * >> WRITING DRIVERS <<
  60. *
  61. * You find information on this subject in the other autodoc file supplied
  62. * with the ProNET distribution.
  63. *
  64. *****************************************************************************
  65. *
  66. *
  67.  
  68.         include    "A:OSmacros.i"
  69.         include    "exec/exec.i"
  70.         include    "dos/dosextens.i"
  71.         include    "devices/timer.i"
  72.         include    "P:include/devices/pronet.i"
  73.         include    "exec_lib.i"
  74.         include    "dos_lib.i"
  75.  
  76.         moveq    #-1,d0
  77.         rts
  78.  
  79.         STRUCTURE MyDev,LIB_SIZE    *** Device Base
  80.         APTR    pnd_SegList        ;Segment List
  81.         APTR    pnd_UnitList        ;List of all Units
  82.         STRUCT    pnd_Semaphore,SS_SIZE    ;for Single-Threading DevOpen()
  83.         LABEL   pnd_SizeOf
  84.  
  85.         STRUCTURE MyUnit,0        *** Unit Structure
  86.         APTR    pndu_Next
  87.         ULONG    pndu_Number
  88.         UWORD    pndu_OpenCnt
  89.  
  90.         APTR    pndu_ProcName
  91.         APTR    pndu_ProcessID
  92.  
  93.         APTR    pndu_SysBase
  94.         APTR    pndu_DOSBase
  95.         UWORD    pndu_RC
  96.  
  97.         APTR    pndu_MsgPort
  98.         APTR    pndu_MsgBackPort
  99.         APTR    pndu_PortList
  100.  
  101.         APTR    pndu_ConfigString
  102.         STRUCT    pndu_DriverName,30
  103.         BPTR    pndu_DriverSeg
  104.  
  105.         STRUCT    pndu_DriverData,pndd_Size
  106.  
  107.         STRUCT    pndu_PendingReads,12
  108.         STRUCT    pndu_PendingWrites,12
  109.         LABEL    pndu_SizeOf
  110.  
  111.         STRUCTURE PortMember,0        *** One Port of a Unit
  112.         APTR    pndp_Next
  113.         UWORD    pndp_Number
  114.         ULONG    pndp_MsgPort
  115.         LABEL    pndp_SizeOf
  116.  
  117. PNDCMD_ADDPORT    equ    CMD_NONSTD+4
  118. PNDCMD_REMPORT    equ    CMD_NONSTD+5
  119.  
  120. LibResident    dc.w    RTC_MATCHWORD
  121.         dc.l    LibResident
  122.         dc.l    EndResident
  123.         dc.b    RTF_AUTOINIT
  124.         dc.b    VERSION
  125.         dc.b    NT_DEVICE
  126.         dc.b    0
  127.         dc.l    DevName
  128.         dc.l    IDString
  129.         dc.l    LibInitData
  130.  
  131. DevName        dc.b    "pronet.device",0
  132.         dc.b    "$VER: "
  133. IDString    dc.b    "pronet.device "
  134.         dc.b    (VERSION/10)+48,(VERSION-((VERSION/10)*10))+48,".",REVISION+48
  135.         dc.b    " (28.5.99)",13,10,0
  136.         even
  137.  
  138. LibInitData    dc.l    pnd_SizeOf
  139.         dc.l    FuncTab
  140.         dc.l    DataTab
  141.         dc.l    Init
  142.  
  143. FuncTab        dc.l    Open
  144.         dc.l    Close
  145.         dc.l    Expunge
  146.         dc.l    ExtFunc
  147.         dc.l    BeginIO
  148.         dc.l    AbortIO
  149.         dc.l    -1
  150.  
  151. DataTab        INITBYTE   LN_TYPE,NT_DEVICE
  152.         INITLONG   LN_NAME,DevName
  153.         INITBYTE   LIB_FLAGS,LIBF_SUMUSED!LIBF_CHANGED
  154.         INITWORD   LIB_VERSION,VERSION
  155.         INITWORD   LIB_REVISION,REVISION
  156.         INITLONG   LIB_IDSTRING,IDString
  157.         dc.w    0
  158.  
  159. OurBase        dc.l    0
  160.  
  161. *****i* pronet.device/DevInit ***********************************************
  162. *
  163. *   NAME   
  164. *    DevInit -- Device is initialized after being loaded into memory.
  165. *
  166. *   FUNCTION
  167. *    This function used to perform a keyfile check. Not any longer.
  168. *
  169. *****************************************************************************
  170. *
  171. * d0 is *OurBase, a0 is *SegList
  172. * must return NULL for error or *SegList for OK.
  173.  
  174. Init        movem.l    d1-d7/a0-a6,-(sp)
  175.         move.l    d0,a5
  176.         move.l    a5,OurBase
  177.         move.l    a0,pnd_SegList(a5)
  178.  
  179.         move.l    a5,a4        ;Device startupped correctly
  180.  
  181. * We need this SignalSemaphore to artificially single-thread our Open
  182. * routine, because we break the exec single-threading by WaitIO.
  183.         lea    pnd_Semaphore+SS_SIZE(a5),a0
  184.         moveq    #SS_SIZE/2-1,d0
  185. .clrsema    clr.w    -(a0)
  186.         dbra    d0,.clrsema
  187.         LIBCALL    InitSemaphore
  188.  
  189.         move.l    a4,d0
  190.         movem.l    (sp)+,d1-d7/a0-a6
  191.         rts
  192.  
  193.         dc.l    $0BADD00D
  194.  
  195. ******* pronet.device/OpenDevice ********************************************
  196. *
  197. *   NAME   
  198. *    OpenDevice -- Open up a new port of a certain ProNET Unit.
  199. *
  200. *   SYNOPSIS
  201. *    error = OpenDevice("pronet.device", unit, ioRequest, flags);
  202. *       D0                  A0              D0    A1         D1
  203. *
  204. *    BYTE OpenDevice(STRPTR, ULONG, struct PNRequest*, ULONG);
  205. *
  206. *   FUNCTION
  207. *    This is an exec.library call.
  208. *
  209. *    Hey, what do you think it does?!??
  210. *
  211. *   INPUTS
  212. *    unit - This number must be defined in the `DEVS:ProNET/.config' file,
  213. *        otherwise OpenDevice() will return PNDERR_UNIT_NOT_DEFINED.
  214. *    ioRequest - A pointer to an initialized (see below) PNRequest block.
  215. *    flags - As described in the overview page, you have the option
  216. *        to get extensive error messages when setting a bit here.
  217. *        The bit is defined as PNB_ERRORSTRING (the PNF_ definition also
  218. *        exists).
  219. *
  220. *    Two components of the PNRequest must be initialized before calling
  221. *    OpenDevice():
  222. *
  223. *    pnr_MsgPort - pointer to a MsgPort where incoming data is sent to.
  224. *    pnr_NetSourcePort - The port number you want to open.
  225. *
  226. *   RESULT
  227. *    error - zero if everything went o.k., otherwise an error code
  228. *        as defined in exec/errors.h or devices/pronet.h.
  229. *
  230. *   NOTES
  231. *    The *one and only* valid port numbers are 0x0001 to 0x7fff. If you
  232. *    want a special number above 0x7fff reserved for your application,
  233. *    please contact me!
  234. *
  235. *    If you don't have any special preferences for your port number,
  236. *    you can use PNP_NEXTFREE to let pronet.device assign you the next
  237. *    free one (it will be put into pnr_NetSourcePort then).
  238. *
  239. *****************************************************************************
  240. *
  241.  
  242. Open        movem.l    a2-a6/d2-d7,-(sp)
  243. ; Any AllocMem could call our Expunge vector, so prevent that by faking
  244. ; an opener!
  245.         addq.w    #1,LIB_OPENCNT(a6)
  246.  
  247.         move.l    d0,d6            ;Unit
  248.         move.l    a1,a2            ;IORequest
  249.         move.l    a6,a5            ;DevBase
  250.         move.l    d1,pnr_Length(a2)
  251.         move.l    4.w,a6
  252.  
  253. * We do this so that InitUnit can modify OurBase->pnd_UnitList without
  254. * danger. Forbid/Permit sucks...
  255.         lea    pnd_Semaphore(a5),a0
  256.         LIBCALL    ObtainSemaphore
  257.  
  258.         move.b    #IOERR_OPENFAIL,IO_ERROR(a2)
  259.  
  260.         * Does the required Unit already exist?
  261.         lea    pnd_UnitList(a5),a3
  262. .searchunit    move.l    (a3),d0
  263.         beq.s    .newunit
  264.         move.l    d0,a3
  265.         cmp.l    pndu_Number(a3),d6
  266.         bne.s    .searchunit
  267.         bra.s    .unitok
  268.  
  269.         * No! So create a Unit!
  270. .newunit    bsr    InitUnit
  271.         tst.l    d0
  272.         beq.s    .ende
  273.         move.l    d0,a3
  274.  
  275.         * Yes! Add new port now! Unit-Structure in a3
  276. .unitok        move.w    #PNDCMD_ADDPORT,IO_COMMAND(a2)
  277.         move.l    a2,a1
  278.         move.l    pndu_MsgPort(a3),a0
  279.         LIBCALL    PutMsg
  280.         move.l    a2,a1
  281.         LIBCALL    WaitIO
  282.         tst.b    d0
  283.         bne.s    .ende
  284.  
  285.         move.l    a3,IO_UNIT(a2)
  286.         addq.w    #1,pndu_OpenCnt(a3)
  287.  
  288.         * Device successfully opened.
  289.         bclr    #LIBB_DELEXP,LIB_FLAGS(a5)
  290.         addq.w    #1,LIB_OPENCNT(a5)
  291.         move.b    #NT_REPLYMSG,LN_TYPE(a2)
  292.         clr.b    IO_ERROR(a2)
  293.  
  294. .ende        lea    pnd_Semaphore(a5),a0
  295.         LIBCALL    ReleaseSemaphore
  296.  
  297.         subq.w    #1,LIB_OPENCNT(a5)
  298.         move.b    IO_ERROR(a2),d0
  299.         beq.s    .0
  300.         move.l    #-1,IO_DEVICE(a2)
  301.         move.l    #-1,IO_UNIT(a2)
  302. .0        movem.l    (sp)+,a2-a6/d2-d7
  303.         rts
  304.  
  305. ; -- Create new Unit
  306. InitUnit    ; a5 *DevBase
  307.         ; a2 *IORequest
  308.         ; d6 Unit
  309.         ; RETURNS d0 *Unit-Structure or NULL
  310.         moveq    #0,d7
  311.  
  312.         move.l    4.w,a6
  313.         lea    dosname(pc),a1
  314.         moveq    #0,d0
  315.         LIBCALL    OpenLibrary
  316.         move.l    d0,d5
  317.         beq    .nodos
  318.  
  319.         move.l    #pndu_SizeOf,d0
  320.         move.l    #MEMF_PUBLIC!MEMF_CLEAR,d1
  321.         LIBCALL    AllocMem
  322.         tst.l    d0
  323.         beq    .nomem1
  324.         move.l    d0,a3
  325.  
  326.         move.l    d6,pndu_Number(a3)
  327.  
  328.         moveq    #32,d0
  329.         move.l    #MEMF_PUBLIC,d1
  330.         LIBCALL    AllocMem
  331.         tst.l    d0
  332.         beq.s    .nomem2
  333.         move.l    d0,a4
  334.  
  335.         move.l    a4,pndu_ProcName(a3)
  336.  
  337.         move.l    d6,-(sp)
  338.         pea    FormatString(pc)
  339.         move.l    a4,-(sp)
  340.         bsr    _mysprintf
  341.         add.w    #12,sp
  342.  
  343.         * First, create Unit process
  344.         move.l    d5,a6
  345.         move.l    a4,d1
  346.         moveq    #0,d2
  347.         move.l    #ProcessCode-4,d3
  348.         lsr.l    #2,d3
  349.         move.l    #4096,d4
  350.         LIBCALL    CreateProc
  351.         move.l    d0,pndu_ProcessID(a3)
  352.         beq.s    .noprocess
  353.  
  354. * Notify process about Unit number, this is the only message we send
  355. * to the Process MsgPort, all the others from BeginIO go to a new MsgPort
  356. * that is created while the Process' initialization.
  357.         move.l    4.w,a6
  358.         move.l    a2,a1
  359.         move.l    a3,IO_UNIT(a1)
  360.         clr.b    IO_FLAGS(a1)
  361.         move.l    d0,a0
  362.         LIBCALL    PutMsg
  363.  
  364.         * Wait for Process to finish initialization
  365.         move.l    a2,a1
  366.         LIBCALL    WaitIO
  367.         tst.b    d0
  368.         bne.s    .noprocess
  369.  
  370.         * Now add this Unit-Structure to our internal List!!
  371.         lea    pnd_UnitList(a5),a0
  372.         move.l    (a0),(a3)
  373.         move.l    a3,(a0)
  374.         move.l    a3,d7
  375.         bra.s    .nomem1
  376.  
  377. .noprocess    move.l    4.w,a6
  378.         move.l    a4,a1
  379.         moveq    #32,d0
  380.         LIBCALL    FreeMem
  381. .nomem2        move.l    a3,a1
  382.         move.l    #pndu_SizeOf,d0
  383.         LIBCALL    FreeMem
  384. .nomem1        move.l    d5,a1
  385.         LIBCALL    CloseLibrary
  386. .nodos        move.l    d7,d0
  387.         rts
  388.  
  389. ******* pronet.device/CloseDevice *******************************************
  390. *
  391. *   NAME   
  392. *    CloseDevice -- Close a port of a certain ProNET Unit.
  393. *
  394. *   SYNOPSIS
  395. *    CloseDevice(PNRequest);
  396. *                   A1
  397. *
  398. *   FUNCTION
  399. *    This is an exec.library call.
  400. *
  401. *    This function terminates access to the corresponding ProNET Unit.
  402. *    Since the Unit is not shut down automatically, even if you were
  403. *    the last user of it, a RemDevice() would be the right thing to
  404. *    do after closing pronet.device.
  405. *
  406. *   INPUTS
  407. *    PNRequest - A pointer to a previously opened ProNET IO Request.
  408. *
  409. *   EXAMPLE
  410. *    This code can force a specified device to try and expunge.
  411. *    Of course, if the device is in use nothing will happen:
  412. *
  413. *    void FlushDevice(name)
  414. *    char  *name;
  415. *    {
  416. *    struct Device *result;
  417. *
  418. *        Forbid();
  419. *        if(result=(struct Device *)FindName(&SysBase->DeviceList,name))
  420. *        RemDevice(result);
  421. *        Permit();
  422. *    }
  423. *
  424. *   SEE ALSO
  425. *    exec.library/CloseDevice(), exec.library/RemDevice()
  426. *
  427. *****************************************************************************
  428. *
  429. *
  430.  
  431. Close        movem.l    a2/a5,-(sp)
  432.         move.l    a1,a2
  433.         move.l    a6,a5
  434.  
  435.         move.l    4.w,a6
  436.         move.l    IO_UNIT(a1),a0
  437.         subq.w    #1,pndu_OpenCnt(a0)
  438.         move.l    pndu_MsgPort(a0),a0
  439.         move.w    #PNDCMD_REMPORT,IO_COMMAND(a1)
  440.         LIBCALL    PutMsg
  441.         move.l    a2,a1
  442.         LIBCALL    WaitIO
  443.  
  444.         move.l    a2,a1
  445.         move.l    a5,a6
  446.         move.l    #-1,IO_DEVICE(a1)
  447.         move.l    #-1,IO_UNIT(a1)
  448.  
  449.         subq.w    #1,LIB_OPENCNT(a6)
  450.         moveq    #0,d0
  451.         movem.l    (sp)+,a2/a5
  452.         rts
  453.  
  454. ; -- This routine was kept free by Commodore for about 10 years now ;)
  455. ExtFunc        moveq    #0,d0
  456.         rts
  457.  
  458. *****i* pronet.device/BeginIO ***********************************************
  459. *
  460. *   NAME   
  461. *    BeginIO -- Execute a device command.
  462. *
  463. *   FUNCTION
  464. *    This is an exec.library call.
  465. *
  466. *    We don't support any QUICK operations, so this bit is cleared
  467. *    in any case.
  468. *
  469. *****************************************************************************
  470. *
  471. *
  472.  
  473. BeginIO        move.l    a6,-(sp)
  474.         move.b    #NT_MESSAGE,LN_TYPE(a1)
  475.         bclr    #IOB_QUICK,IO_FLAGS(a1)
  476.         clr.b    IO_ERROR(a1)
  477.         move.l    IO_UNIT(a1),a0
  478.         move.l    pndu_MsgPort(a0),a0
  479.         move.l    4.w,a6
  480.         LIBCALL    PutMsg
  481.         move.l    (sp)+,a6
  482.         rts
  483.  
  484. *****i* pronet.device/AbortIO ***********************************************
  485. *
  486. *   NAME   
  487. *    AbortIO -- Abort a currently queued IO request.
  488. *
  489. *   FUNCTION
  490. *    This is an exec.library call.
  491. *
  492. *    Sorry folks, we don't support AbortIO.
  493. *
  494. *****************************************************************************
  495. *
  496. *
  497.  
  498. AbortIO        moveq    #0,d0            ;Gar nix geht ab hier.
  499.         rts
  500.  
  501. *****i* pronet.device/Expunge ***********************************************
  502. *
  503. *   NAME   
  504. *    Expunge -- Prepare device removal.
  505. *
  506. *   FUNCTION
  507. *    This is an exec.library call.
  508. *
  509. *    We return *SegList if the device can be deallocated or NULL if we
  510. *    have still openers.
  511. *
  512. *    Even if we have openers, we try to get rid of all unused Units.
  513. *
  514. *****************************************************************************
  515. *
  516. *
  517.  
  518. Expunge        movem.l    d2-d7/a2-a6,-(sp)
  519.  
  520.         move.l    a6,a5
  521.         move.l    4.w,a6
  522.  
  523.         sub.l    a1,a1
  524.         LIBCALL    FindTask
  525.         move.l    d0,expungetask
  526.  
  527.         moveq    #-1,d0
  528.         LIBCALL    AllocSignal
  529.         move.b    d0,expungesignal
  530.         move.b    d0,d7
  531.         bmi.s    .delexp
  532.  
  533.         lea    pnd_UnitList(a5),a3
  534. .browseunits    move.l    a3,a4            ;a4=lastpt
  535.         move.l    (a3),d0
  536. .browseunitse    beq.s    .nomoreunits
  537.         move.l    d0,a3            ;a3=current
  538.  
  539.         tst.w    pndu_OpenCnt(a3)
  540.         bne.s    .browseunits
  541.  
  542.         move.l    pndu_ProcessID(a3),a1
  543.         lea    -pr_MsgPort(a1),a1
  544.         move.l    #SIGBREAKF_CTRL_C,d0
  545.         LIBCALL    Signal
  546.  
  547.         moveq    #0,d0
  548.         bset    d7,d0
  549.         LIBCALL    Wait
  550.  
  551.         move.l    pndu_ProcName(a3),a1
  552.         moveq    #32,d0
  553.         LIBCALL    FreeMem
  554.  
  555.         move.l    (a3),d2
  556.         move.l    d2,(a4)
  557.         move.l    a3,a1
  558.  
  559.         move.l    #pndu_SizeOf,d0
  560.         LIBCALL    FreeMem
  561.         move.l    d2,d0
  562.         bra.s    .browseunitse
  563.  
  564. .nomoreunits    move.b    d7,d0
  565.         LIBCALL    FreeSignal
  566.         tst.w    LIB_OPENCNT(a5)
  567.         beq.s    .expunge
  568. .delexp        moveq    #0,d0
  569.         bset    #LIBB_DELEXP,LIB_FLAGS(a6)
  570.         bra.s    .ende
  571.  
  572. .expunge    move.l    pnd_SegList(a5),d2    ;The whole Device is not used,
  573.         move.l    a5,a1            ;so quit everything!
  574.         LIBCALL    Remove
  575.         move.l    a5,a1
  576.         moveq    #0,d0
  577.         move.w    LIB_NEGSIZE(a5),d0
  578.         sub.l    d0,a1
  579.         add.w    LIB_POSSIZE(a5),d0
  580.         LIBCALL    FreeMem
  581.  
  582.         move.l    d2,d0
  583. .ende        movem.l    (sp)+,d2-d7/a2-a6
  584.         rts
  585.  
  586. expungetask    dc.l    0
  587. expungesignal    dc.b    0,0
  588.  
  589. ** -----------------------------------------------------------------------
  590. **
  591. **
  592. **
  593. **
  594.  
  595. **
  596. ** DeviceUnit Process Code
  597. **
  598.  
  599. **
  600. **
  601. **
  602. **
  603. ** -----------------------------------------------------------------------
  604.  
  605.         cnop    0,4
  606.  
  607. * First we will receive the first requestor's IORequest as a startup
  608. * message. It contains the Unit structure in IO_UNIT. We must init
  609. * and return with an error code in IO_ERROR.
  610.  
  611. ProcessCode    move.l    4.w,a6
  612.         sub.l    a1,a1
  613.         LIBCALL    FindTask
  614.         move.l    d0,a2
  615.         lea    pr_MsgPort(a2),a2
  616.         move.l    a2,a0
  617.         LIBCALL    WaitPort
  618.         move.l    a2,a0
  619.         LIBCALL    GetMsg
  620.         move.l    d0,a3
  621.  
  622.         move.b    #IOERR_OPENFAIL,IO_ERROR(a3)    ;[a3] Startupmsg
  623.         move.l    IO_UNIT(a3),a5
  624.         st    pndu_RC(a5)
  625.  
  626. * Get Library Bases. We do *not* do it once in DevInit, but for every
  627. * new process, since all this shit could (and will) change with PowerPC.
  628.         move.l    a6,pndu_SysBase(a5)
  629.         lea    dosname(pc),a1
  630.         moveq    #0,d0
  631.         LIBCALL    OpenLibrary
  632.         move.l    d0,pndu_DOSBase(a5)
  633.         beq    .nodos
  634.  
  635.         lea    pndu_PendingReads(a5),a1
  636.         NEWLIST    a1
  637.         lea    pndu_PendingWrites(a5),a1
  638.         NEWLIST    a1
  639.  
  640. * Get port for messages replied from the applications
  641.         bsr    CreatePort
  642.         move.l    d0,pndu_MsgBackPort(a5)
  643.         beq    .noport
  644.  
  645. * Get new port for all the messages arriving from BeginIO()
  646.         bsr    CreatePort
  647.         move.l    d0,pndu_MsgPort(a5)
  648.         beq    .noport2
  649.  
  650. * Get configuration string for our Unit
  651.         move.l    pndu_Number(a5),d0
  652.         bsr    getconfigstr
  653.         move.b    #PNDERR_UNIT_NOT_DEFINED,IO_ERROR(a3)
  654.         move.l    d0,pndu_ConfigString(a5)
  655.         beq.s    .noconf
  656.  
  657. * Load and start the driver
  658.         move.b    #PNDERR_DRIVERTROUBLE,IO_ERROR(a3)
  659.         bsr    StartDriver
  660.         tst.l    d0
  661.         bne.s    .nodriver
  662.  
  663. * Everything went O.K. -> Push back the startup packet and start working!
  664.         clr.b    IO_ERROR(a3)
  665.         move.l    a3,a1
  666.         LIBCALL    ReplyMsg
  667.  
  668.         clr.w    pndu_RC(a5)
  669.  
  670.         bsr    MainLoop
  671.  
  672.         bsr    StopDriver
  673. .nodriver    move.l    pndu_ConfigString(a5),a0
  674.         bsr    freeconfigstr
  675. .noconf        move.l    pndu_MsgPort(a5),a0
  676.         bsr    DeletePort
  677. .noport2    move.l    pndu_MsgBackPort(a5),a0
  678.         bsr    DeletePort
  679. .noport        move.l    pndu_DOSBase(a5),a1
  680.         move.l    4.w,a6
  681.         LIBCALL    CloseLibrary
  682. .nodos        tst.w    pndu_RC(a5)
  683.         beq.s    .returnfinal
  684.         LIBCALL    Forbid        ;Use Forbid() to prevent Exec from a task change
  685.         move.l    a3,a1        ;between ReplyMsg and the complete discard of the
  686.         LIBJMP    ReplyMsg    ;process!
  687.  
  688. .returnfinal    LIBCALL    Forbid
  689.         move.l    expungetask(pc),a1
  690.         moveq    #0,d0
  691.         move.b    expungesignal(pc),d1
  692.         bset    d1,d0
  693.         LIBJMP    Signal
  694.  
  695. * These routines handle the configuration file:
  696.  
  697. ; -- Obtain configuration string
  698. getconfigstr    ; d0 number (0..n)
  699.         ; a5 *pndu
  700.         ; RETURNS d0 *line-string or NULL if it doesn't exist
  701.         movem.l    d2-d7/a2-a6,-(sp)
  702.         move.l    d0,a2
  703.         moveq    #0,d4            ;[d4] RC
  704.  
  705.         * Read Config File
  706.         move.l    pndu_DOSBase(a5),a6
  707.         move.l    #configname,d1
  708.         move.l    #MODE_OLDFILE,d2
  709.         LIBCALL    Open
  710.         move.l    d0,d7
  711.         beq    .nofile
  712.  
  713.         move.l    d7,d1
  714.         moveq    #0,d2
  715.         move.l    #OFFSET_END,d3
  716.         LIBCALL    Seek
  717.         move.l    d7,d1
  718.         moveq    #0,d2
  719.         move.l    #OFFSET_BEGINNING,d3
  720.         LIBCALL    Seek
  721.  
  722.         addq.l    #1,d0
  723.         move.l    d0,d5            ;[d5] configmemsize
  724.         move.l    #MEMF_CLEAR,d1
  725.         move.l    pndu_SysBase(a5),a6
  726.         LIBCALL    AllocMem
  727.         tst.l    d0
  728.         beq    .nomem
  729.         move.l    d0,a3            ;[a3] configmem
  730.         move.l    d0,a4
  731.  
  732.         move.l    d7,d1
  733.         move.l    a3,d2
  734.         move.l    d5,d3
  735.         subq.l    #1,d3
  736.         move.l    pndu_DOSBase(a5),a6
  737.         LIBCALL    Read
  738.         cmp.l    d0,d3
  739.         bne.s    .readerr
  740.  
  741.         * Now search the line ID
  742.         move.l    a2,d2
  743. .loop        subq.w    #1,d2
  744.         bcc.s    .next
  745.  
  746.         * Get string length
  747.         move.l    a3,a0
  748. .getlen        move.b    (a0)+,d0
  749.         cmp.b    #32,d0
  750.         bcc.s    .getlen
  751.         sub.l    a3,a0
  752.         move.l    a0,d0
  753.         subq.l    #1,d0
  754.         beq.s    .readerr
  755.  
  756.         * Copy string
  757.         move.w    d0,d2
  758.         addq.l    #5,d0            ;EOS + Length Tracking
  759.         move.l    d0,d3
  760.         move.l    pndu_SysBase(a5),a6
  761.         moveq    #MEMF_PUBLIC,d1
  762.         LIBCALL    AllocMem
  763.         tst.l    d0
  764.         beq.s    .readerr
  765.  
  766.         move.l    d0,a0
  767.         move.l    d3,(a0)+
  768.         move.l    a0,d4
  769.         subq.w    #1,d2
  770. .copy        move.b    (a3)+,(a0)+
  771.         dbra    d2,.copy
  772.         clr.b    (a0)+
  773.         bra.s    .readerr
  774.  
  775.         * Jump to next line
  776. .next        move.b    (a3)+,d0
  777.         beq.s    .readerr
  778.         cmp.b    #10,d0
  779.         beq.s    .loop
  780.         bra.s    .next
  781.  
  782. .readerr    move.l    a4,a1
  783.         move.l    d5,d0
  784.         move.l    pndu_SysBase(a5),a6
  785.         LIBCALL    FreeMem
  786.  
  787. .nomem        move.l    d7,d1
  788.         move.l    pndu_DOSBase(a5),a6
  789.         LIBCALL    Close
  790.  
  791. .nofile        move.l    d4,d0
  792. .ende        movem.l    (sp)+,d2-d7/a2-a6
  793.         rts
  794.  
  795. ; -- Dispose configuration string
  796. freeconfigstr    ; a0 *line-string got by 'getconfigstr'
  797.         move.l    a6,-(sp)
  798.         move.l    -(a0),d0
  799.         move.l    a0,a1
  800.         move.l    pndu_SysBase(a5),a6
  801.         LIBCALL    FreeMem
  802.         move.l    (sp)+,a6
  803.         rts
  804.  
  805. ; -- Load the interface driver and initialize it.
  806. StartDriver    ; RETURNS d0 <>NULL on failure!
  807.         movem.l    a2/a6,-(sp)
  808.         lea    pndu_DriverName(a5),a1
  809.         lea    driverpath(pc),a0
  810. .l0        move.b    (a0)+,(a1)+
  811.         bne.s    .l0
  812.  
  813.         subq.l    #1,a1
  814.         move.l    a1,a2
  815.         move.l    pndu_ConfigString(a5),a0
  816. .l1        move.b    (a0)+,d0
  817.         move.b    d0,(a1)+
  818.         cmp.b    #" ",d0
  819.         bhi.s    .l1
  820.         clr.b    -(a1)
  821.         move.l    a0,d6
  822.  
  823.         move.l    pndu_DOSBase(a5),a6
  824.         lea    pndu_DriverName(a5),a1
  825.         move.l    a1,d1
  826.         LIBCALL    LoadSeg
  827.         move.l    d0,pndu_DriverSeg(a5)    ;(a5) was missing in V2 & V3 -> Enforcer hit!
  828.         bne.s    .c1
  829.         move.l    #mc_err3,d0
  830.         bra.s    .0000
  831. .c1        add.l    d0,d0
  832.         add.l    d0,d0
  833.         addq.l    #4,d0
  834.         move.l    d0,a2
  835.  
  836.         * And now, Ladies & Gentlemen :))
  837.         lea    pndu_DriverData(a5),a0
  838.         move.l    d6,a1        ;ConfString after Driver-ID
  839.         move.l    #"RST!",d0
  840.         moveq    #2,d1        ;ProNET >V3
  841.         jsr    (a2)
  842.         tst.l    d0
  843.         beq.s    .ende
  844.  
  845.         * Copy the extensive error message when requested.
  846. .0000        btst    #PNB_ERRORSTRING,pnr_Length+3(a3)
  847.         beq.s    .error2
  848.         cmp.l    #PNDRVERR_NO_MEMORY,d0
  849.         bne.s    .000
  850.         move.l    #mc_err1,d0
  851. .000        cmp.l    #PNDRVERR_WRONG_ARGS,d0
  852.         bne.s    .001
  853.         move.l    #mc_err2,d0
  854. .001        move.l    d0,a0
  855.  
  856.         move.l    pnr_Data(a3),a1
  857.         moveq    #62,d0
  858. .00cpy        move.b    (a0)+,(a1)+
  859.         dbeq    d0,.00cpy
  860.         clr.b    (a1)+
  861.  
  862. .error2        move.l    pndu_DOSBase(a5),a6
  863.         move.l    pndu_DriverSeg(a5),d1
  864.         beq.s    .error
  865.         LIBCALL    UnLoadSeg
  866.  
  867. .error        moveq    #-1,d0
  868. .ende        movem.l    (sp)+,a2/a6
  869.         rts
  870.  
  871. ; -- Cancel the interface driver
  872. StopDriver    move.l    pndu_DriverData+pndd_Exit(a5),a0
  873.         jsr    (a0)
  874.  
  875.         move.l    pndu_DOSBase(a5),a6
  876.         move.l    pndu_DriverSeg(a5),d1
  877.         LIBCALL    UnLoadSeg
  878.         rts
  879.  
  880. ******************
  881. ; -- The Main Loop
  882. ******************
  883.  
  884. MainLoop
  885.         move.l    pndu_MsgBackPort(a5),a0
  886.         move.b    MP_SIGBIT(a0),d2
  887.         move.b    pndu_DriverData+pndd_ReadSignalBit(a5),d3
  888.         move.l    pndu_MsgPort(a5),a0
  889.         move.b    MP_SIGBIT(a0),d4
  890.         moveq    #0,d5
  891.         bset    #SIGBREAKB_CTRL_C,d5
  892.         bset    d2,d5
  893.         bset    d3,d5
  894.         bset    d4,d5            ;[d5] Signalmask to wait for
  895.         movem.l    a6/d2-d5,-(sp)
  896.  
  897. Wait4Msg    movem.l    (sp),a6/d2-d5
  898.         bsr    CheckWrites
  899.         move.l    d5,d0
  900.         LIBCALL    Wait
  901.         btst    #SIGBREAKB_CTRL_C,d0
  902.         bne.s    StopThisShit
  903.         movem.l    d0/d3/d4,-(sp)
  904.         btst    d2,d0
  905.         bne    MessageBack
  906. wait1        movem.l    (sp),d0/d3/d4
  907.         btst    d3,d0
  908.         bne    ReceiveData
  909. wait2        movem.l    (sp)+,d0/d3/d4
  910.         btst    d4,d0
  911.         bne    MessageLoop
  912.         bra    Wait4Msg
  913. StopThisShit    movem.l    (sp)+,a6/d2-d5
  914.         rts
  915.  
  916. ; -- Look at the history, 31-05-95 for reasons why we do this!
  917. CheckWrites
  918.         lea    pndu_PendingWrites(a5),a0
  919.         TSTLIST    a0
  920.         beq.s    .okay
  921.         move.b    pndu_DriverData+pndd_ReadSignalBit(a5),d0
  922.         moveq    #0,d1
  923.         bset    d0,d1
  924.         moveq    #-1,d0
  925.         LIBCALL    SetSignal
  926. .okay        rts
  927.  
  928. *****i* pronet.device/ReceiveData *******************************************
  929. *
  930. *   NAME   
  931. *    ReceiveData -- read incoming data from driver.
  932. *
  933. *****************************************************************************
  934. *
  935. *
  936.  
  937. ******* pronet.device/ReceivedData ******************************************
  938. *
  939. * Received data will be sent to the MsgPort you specified in pnr_MsgPort
  940. * when opening the device. You can not change it after opening.
  941. * mn_Length, as opposed to pre-v37, contains the length of the whole Message
  942. * structure. The first word of mn_Node.ln_Name contains the source ProNET
  943. * Port, the second word contains the destination port. The data comes behind
  944. * the Message structure.
  945. *
  946. * This Message must be replied as soon as there is no use for it any more.
  947. *
  948. * If there is incoming data but pronet.device can't allocate the Message
  949. * structure, the packet is lost!
  950. *
  951. *****************************************************************************
  952. *
  953. *
  954.  
  955. ReceiveData
  956.         move.l    pndu_DriverData+pndd_ReadQuery(a5),a0    ;Do external driver magic..
  957.         jsr    (a0)
  958.  
  959.         * d0.w length (if NULL then exit!!!)
  960.         * d1 destination port
  961.         * d2 source port
  962.         ext.l    d0
  963.         beq    .ende
  964.         move.w    d1,d7
  965.         move.w    d2,d5
  966.         add.l    #MN_SIZE,d0
  967.         move.l    d0,d6
  968.  
  969. .tryagain    moveq    #MEMF_PUBLIC,d1
  970.         LIBCALL    AllocMem
  971.         tst.l    d0
  972.         bne.s    .memok
  973.  
  974.         * No memory! Forget it! (ProNET <=V3 would busy wait until
  975.         * memory is free. This was BAD!)
  976.         move.l    pndu_DriverData+pndd_ReadFlush(a5),a0
  977.         jsr    (a0)
  978.         bra.s    .ende
  979.  
  980.         * Now get the data and build a Message
  981. .memok        move.l    d0,a3
  982.         lea    MN_SIZE(a3),a0
  983.         move.l    pndu_DriverData+pndd_Read(a5),a1
  984.         jsr    (a1)
  985.         move.w    d5,LN_NAME(a3)
  986.         move.w    d7,LN_NAME+2(a3)
  987.         move.w    d6,MN_LENGTH(a3)
  988.         move.l    pndu_MsgBackPort(a5),MN_REPLYPORT(a3)
  989.         move.b    #NT_MESSAGE,LN_TYPE(a3)
  990.  
  991.         lea    pndu_PendingReads(a5),a0
  992.         move.l    a3,a1
  993.         LIBCALL    AddTail
  994.  
  995. .ende        bsr    TryPendingReads
  996.         bsr    TryPendingWrites
  997.         bra    wait2
  998.  
  999. *****i* pronet.device/MessageLoop *******************************************
  1000. *
  1001. *   NAME   
  1002. *    MessageLoop -- process applications' commands.
  1003. *
  1004. *   FUNCTION
  1005. *    We got a new request from one of our clients.. well we could say we
  1006. *    are currently busy but then he would use ParNet ;-)
  1007. *
  1008. *****************************************************************************
  1009. *
  1010. *
  1011.  
  1012. MessageLoop
  1013.         move.l    pndu_MsgPort(a5),a0
  1014.         LIBCALL    GetMsg
  1015.         tst.l    d0
  1016.         beq    Wait4Msg        ;no more messages
  1017.         move.l    d0,a2
  1018.         move.w    IO_COMMAND(a2),d0
  1019.  
  1020.         cmp.w    #CMD_WRITE,d0
  1021.         beq    CMD__WRITE
  1022.         cmp.w    #PNDCMD_ADDPORT,d0
  1023.         beq    CMD__ADDPORT
  1024.         cmp.w    #PNDCMD_REMPORT,d0
  1025.         beq    CMD__REMPORT
  1026.  
  1027.         move.b    #IOERR_NOCMD,IO_ERROR(a2)
  1028.         move.l    a2,a1
  1029.         LIBCALL    ReplyMsg
  1030.         bra    MessageLoop
  1031.  
  1032. *****i* pronet.device/CMD_ADDPORT *******************************************
  1033. *
  1034. *   NAME   
  1035. *    AddPort -- New device opener.
  1036. *
  1037. *****************************************************************************
  1038. *
  1039. *
  1040.  
  1041. CMD__ADDPORT
  1042.         move.w    pnr_NetSourcePort(a2),d1
  1043.         cmp.w    #PNP_NEXTFREE,d1
  1044.         bne.s    .0
  1045.         moveq    #1,d1
  1046.         lea    pndu_PortList(a5),a1
  1047. .next        move.l    a1,a0
  1048. .loop1        move.l    (a0),d0
  1049.         beq.s    .notfound
  1050.         move.l    d0,a0
  1051.         cmp.w    pndp_Number(a0),d1
  1052.         bne.s    .loop1
  1053.         addq.w    #1,d1
  1054.         bra.s    .next
  1055. .notfound    move.w    d1,pnr_NetSourcePort(a2)
  1056.  
  1057. .0        move.b    #IOERR_OPENFAIL,IO_ERROR(a2)
  1058.  
  1059.         * See if port already exists, portnumber in d1 now
  1060.         lea    pndu_PortList(a5),a0
  1061. .loop0        move.l    (a0),d0
  1062.         beq.s    .ok
  1063.         move.l    d0,a0
  1064.         cmp.w    pndp_Number(a0),d1
  1065.         bne.s    .loop0
  1066.         * Sorry
  1067.         move.b    #PNDERR_PORTEXISTS,IO_ERROR(a2)
  1068.         bra.s    .ende
  1069.  
  1070.         * No, add it!
  1071. .ok        moveq    #pndp_SizeOf,d0
  1072.         moveq    #0,d1
  1073.         LIBCALL    AllocMem
  1074.         tst.l    d0
  1075.         beq.s    .ende
  1076.  
  1077.         move.l    d0,a4
  1078.         move.w    pnr_NetSourcePort(a2),pndp_Number(a4)
  1079.         move.l    pnr_MsgPort(a2),pndp_MsgPort(a4)
  1080.         lea    pndu_PortList(a5),a0
  1081.         move.l    (a0),(a4)
  1082.         move.l    a4,(a0)
  1083.  
  1084.         bsr    TryPendingReads
  1085.  
  1086.         clr.b    IO_ERROR(a2)        ;Okay, port added
  1087. .ende        move.l    a2,a1
  1088.         LIBCALL    ReplyMsg
  1089.         bra    MessageLoop
  1090.  
  1091. *****i* pronet.device/CMD_REMPORT *******************************************
  1092. *
  1093. *   NAME   
  1094. *    RemPort -- Device is closed.
  1095. *
  1096. *****************************************************************************
  1097. *
  1098. *
  1099.  
  1100. CMD__REMPORT
  1101.         move.w    pnr_NetSourcePort(a2),d2
  1102.         lea    pndu_PortList(a5),a1
  1103. .find        move.l    a1,a3
  1104.         move.l    (a1),d0
  1105.         beq.s    .notfound
  1106.         move.l    d0,a1
  1107.         cmp.w    pndp_Number(a1),d2
  1108.         bne.s    .find
  1109.         move.l    (a1),d2
  1110.         moveq    #pndp_SizeOf,d0
  1111.         LIBCALL    FreeMem
  1112.         move.l    d2,(a3)        ;Teil aus der Liste entfernt !!
  1113.         move.l    a2,a1
  1114.         LIBCALL    ReplyMsg
  1115. .notfound    bra    MessageLoop
  1116.  
  1117. ******* pronet.device/CMD_WRITE *********************************************
  1118. *
  1119. *   NAME   
  1120. *    Write -- send output to ProNET Port.
  1121. *
  1122. *   FUNCTION
  1123. *    This command causes a packet of data to be written out the ProNET
  1124. *    Port/Unit. The number of characters is specified in pnr_Length.
  1125. *
  1126. *   IO REQUEST
  1127. *    io_Command - CMD_WRITE
  1128. *    pnr_Data - pointer to block of data to transmit
  1129. *    pnr_Length - number of characters to transmit. MUST BE EVEN AND MUST
  1130. *        NOT BE GREATER THAN 0x4000!
  1131. *
  1132. *   RESULTS
  1133. *    io_Error - if the Write succeeded, then io_Error will be zero.
  1134. *        The only other possible error code is PNDERR_DESTINATION_GONE.
  1135. *
  1136. *****************************************************************************
  1137. *
  1138. *
  1139.  
  1140. CMD__WRITE
  1141.         move.l    a2,a1
  1142.         lea    pndu_PendingWrites(a5),a0
  1143.         LIBCALL    AddTail
  1144.         bsr    TryPendingWrites
  1145.         bra    MessageLoop            ;kurz und schmerzlos :-)
  1146.  
  1147. *****i* pronet.device/MessageBack *******************************************
  1148. *
  1149. *   NAME   
  1150. *    MessageBack -- Application replied a ProNET Message.
  1151. *
  1152. *   FUNCTION
  1153. *    Free the message structure and data.
  1154. *
  1155. *****************************************************************************
  1156. *
  1157. *
  1158.  
  1159. MessageBack
  1160.         move.l    pndu_MsgBackPort(a5),a0
  1161.         LIBCALL    GetMsg
  1162.         tst.l    d0
  1163.         beq    wait1
  1164.         move.l    d0,a1
  1165.         moveq    #0,d0
  1166.         move.w    MN_LENGTH(a1),d0
  1167.         LIBCALL    FreeMem
  1168.         bra.s    MessageBack
  1169.  
  1170. *****i* pronet.device/TryPendingReads *******************************************
  1171. *
  1172. *   NAME   
  1173. *    TryPendingReads -- Iterate through this Unit's pending reads list.
  1174. *
  1175. *   FUNCTION
  1176. *    ProNET remembers all messages for ports that are not currently open
  1177. *    and sends them off when they are opened.
  1178. *
  1179. *****************************************************************************
  1180. *
  1181. *
  1182.  
  1183. TryPendingReads
  1184.         move.l    a2,-(sp)
  1185.         lea    pndu_PendingReads(a5),a3
  1186.         move.l    LH_HEAD(a3),a2
  1187.         addq.l    #4,a3
  1188. .looop        cmp.l    a2,a3
  1189.         bne.s    .doit
  1190.         move.l    (sp)+,a2
  1191.         rts
  1192.  
  1193. .doit        move.l    a2,a4
  1194.         move.l    LN_SUCC(a2),a2
  1195.  
  1196.         move.w    LN_NAME+2(a4),d1
  1197.         lea    pndu_PortList(a5),a0
  1198. .find        move.l    (a0),d0
  1199.         beq.s    .looop
  1200.         move.l    d0,a0
  1201.         cmp.w    pndp_Number(a0),d1
  1202.         bne.s    .find
  1203.         move.l    pndp_MsgPort(a0),d5
  1204.         move.l    a4,a1
  1205.         LIBCALL    Remove
  1206.         move.l    d5,a0
  1207.         move.l    a4,a1
  1208.         LIBCALL    PutMsg
  1209.         bra.s    .looop
  1210.  
  1211. *****i* pronet.device/TryPendingWrites **************************************
  1212. *
  1213. *   NAME   
  1214. *    TryPendingWrites -- Process pending write requests.
  1215. *
  1216. *   FUNCTION
  1217. *    This routine checks this Unit on unprocessed write requests and
  1218. *    sends them off if possible.
  1219. *
  1220. *****************************************************************************
  1221. *
  1222. *
  1223.  
  1224. TryPendingWrites
  1225.         move.l    a2,-(sp)
  1226.         lea    pndu_PendingWrites(a5),a3
  1227.         move.l    LH_HEAD(a3),a2
  1228.         addq.l    #4,a3
  1229. .looop        cmp.l    a2,a3
  1230.         bne.s    .doit
  1231. .busy        move.l    (sp)+,a2
  1232.         rts
  1233.  
  1234. .doit        move.l    a2,a4
  1235.         move.l    LN_SUCC(a2),a2
  1236.  
  1237. .noxpk        move.l    pnr_Data(a4),a0
  1238.         move.l    pnr_Length(a4),d0
  1239.         addq.l    #1,d0            ;round up to word boundary
  1240.         bclr    #0,d0
  1241.         move.w    pnr_NetDestPort(a4),d1
  1242.         move.w    pnr_NetSourcePort(a4),d2
  1243.         move.l    pndu_DriverData+pndd_Write(a5),a6
  1244.         jsr    (a6)            ;Send the data
  1245.         move.l    pndu_SysBase(a5),a6
  1246.         tst.w    d0
  1247.         beq.s    .okay
  1248.         bmi.s    .busy
  1249.  
  1250.         * Remote machine doesn't respond, reply CMD_WRITE with
  1251.         * an error.
  1252.         move.l    a4,a1
  1253.         LIBCALL    Remove
  1254.         move.b    #PNDERR_DESTINATION_GONE,IO_ERROR(a4)
  1255.         bra.s    .reply
  1256.  
  1257. .okay        * IORequest done, reply it!
  1258.         move.l    a4,a1
  1259.         LIBCALL    Remove
  1260.         clr.b    IO_ERROR(a4)
  1261. .reply        move.l    a4,a1
  1262.         LIBCALL    ReplyMsg
  1263.         bra    .looop
  1264.  
  1265. ** -----------------------------------------------------------------------
  1266. **
  1267. **
  1268. **
  1269. **
  1270.  
  1271. **
  1272. ** Useful routines
  1273. **
  1274.  
  1275. **
  1276. **
  1277. **
  1278. **
  1279. ** -----------------------------------------------------------------------
  1280.  
  1281. _mysprintf    movem.l a2/a3/a6,-(sp)
  1282.         move.l    4*4(sp),a3      ;Get the output string pointer
  1283.         move.l    5*4(sp),a0       ;Get the FormatString pointer
  1284.         lea    6*4(sp),a1       ;Get the pointer to the DataStream
  1285.         lea    .stuffChar(pc),a2
  1286.         move.l    4.w,a6
  1287.         LIBCALL    RawDoFmt
  1288.         movem.l (sp)+,a2/a3/a6
  1289.         rts
  1290. .stuffChar    move.b    d0,(a3)+        ;Put data to output string
  1291.         rts
  1292.  
  1293.         include    "P:include/devio_ports.s"
  1294.  
  1295. dosname        dc.b    "dos.library",0
  1296. configname    dc.b    "DEVS:ProNET/.config",0
  1297. FormatString    dc.b    "pronet.device (%ld)",0
  1298. driverpath    dc.b    "DEVS:ProNET/",0
  1299. mc_err1        dc.b    "Out of memory.",0
  1300. mc_err2        dc.b    "Wrong arguments in configuration file.",0
  1301. mc_err3        dc.b    "Can't find specified driver module.",0
  1302.         even
  1303.  
  1304. EndResident:
  1305.